#include "header.h"

// 实现 UDP -- 网络聊天室
class Server 
{
public:
    Server(uint16_t port = 44444)
        : mport(port)
        , msock(-1)
        , mip()
    {}

    // 初始化, 获取通信文件描述符 以及 绑定
    void init()
    {
        // 1. 初始化套接字, 网络通信, UDP, 使用默认协议即 UDP
        msock = socket(AF_INET, SOCK_DGRAM, 0);
        // 2. 绑定
        struct sockaddr_in svr;
        memset(&svr, 0, sizeof svr);        // 全部比特位置 0
        //    填写相关数据
        svr.sin_family = AF_INET;
        svr.sin_port = htons(mport);
        svr.sin_addr.s_addr = htonl(INADDR_ANY);        // 选择一个服务可以用的, 一般也都是选择这个

        if (bind(msock, (const sockaddr*) &svr, sizeof svr) != 0) 
        {
            cout << "服务器绑定失败" << endl;
            exit(1);
        }
        cout << "服务器绑定成功" << endl;
    }

    // 服务器开始读取数据
    void run()
    {
        char recvmsg[1024] = {0};
        while (true)
        {
            // 先创建客户端的相关数据结构
            struct sockaddr_in peer;    // 是空的, 作为方法参数的时候, 可以认为是空的缓冲区
            socklen_t len = sizeof peer;
            
            ssize_t rd = recvfrom(msock, recvmsg, 1023, 0, (struct sockaddr*) &peer, &len); // 接收数据
            if (rd > 0)
            {
                recvmsg[rd] = 0;    
                cout << "[服务器收到了数据]: " << recvmsg << endl;
            }
            // 处理一下客户端数据
            uint16_t port = ntohs(peer.sin_port);
            string ip = inet_ntoa(peer.sin_addr);

            saveUser(ip, port, peer);

            // 收到的数据, 进行路由转发
            route(ip, port, recvmsg);
        }
    }

    void saveUser(string ip, uint16_t port, struct sockaddr_in peer)
    {
        string key = ip + ":";
        key += to_string(port);
        if (users.count(key) == 0)  // 如果不存在这个用户
        {
            users.emplace(key, peer);
        }
    }

    void route(string ip, uint16_t port, string msg)
    {
        string result = "[ " + ip + '|';
        result += to_string(port);
        result += "] 回响: " + msg;
        
        for (const pair<string, struct sockaddr_in>& entry : users) 
        {
            sendto(msock, result.c_str(), result.size(), 0, (struct sockaddr*) &entry.second, sizeof entry.second);
        }
    }

private:
    string mip;             // 服务器 IP 地址
    uint16_t mport;         // 服务器端口号
    int msock;              // 服务器通信的套接字
    // 实现广播功能, 记录所有连接的用户
    unordered_map<string, struct sockaddr_in> users;
};

int main()
{
    Server svr;
    svr.init();
    svr.run();
    return 0;
}